#pragma once
#include <string>
#include <cstring>
#include <cassert>

class SView {
 public:
  SView() : data_(nullptr), size_(0) {}
  SView(const char *data, size_t size) : data_(data), size_(size) {}
  SView(std::string &s) : data_(s.data()), size_(s.size()) {}
  SView(const SView&) = default;
  SView& operator=(const SView&) = default;
  inline char operator[](size_t offset) const {
    assert(offset < size_);
    return data_[offset];
  }

  inline const char *data() const { return data_; }
  inline size_t size() const { return size_; }
  inline bool empty() const { return size_ == 0; }
  inline void clear() { data_ = nullptr; size_ = 0; }

  inline void remove_prefix(size_t offset) {
    assert(offset < size_);
    data_ += offset;
    size_ -= offset;
  }
  inline void remove_suffix(size_t offset) {
    assert(offset < size_);
    size_ -= offset;
  }
  inline void truncation(size_t offset, size_t lengh) {
    assert(offset < size_ && offset + lengh < size_);
    data_ += offset;
    size_ = lengh;
  }
  inline SView get_part(size_t offset, size_t lengh) {
    assert(offset < size_ && offset + lengh < size_);
    return SView(data_+offset, lengh);
  }
  inline void reuse(const char *data, size_t size) { data_ = data; size_ = size; }
  inline void reuse(std::string &s) { data_ = s.data(); size_ = s.size(); }
  std::string to_string() const { return std::string(data_, size_); }

 private:
  const char *data_;
  size_t size_;
};

inline bool operator==(const SView &left, const SView &right) {
  return (left.size() == right.size() && 
          memcmp(left.data(), right.data(), left.size()) == 0);
}